﻿using System;
using System.Collections.Generic;
using System.Text;

namespace HZY.Logic.Sys
{
    using System.Linq;
    using System.Threading.Tasks;
    using System.Collections;
    using HZY.DbExtensions;
    using HZY.Models.Sys;
    using HZY.Models;
    using HZY.Toolkit;
    using HZY.DTO.Sys;
    using HZY.Logic.Core;
    using HzySql;
    using HzySql.Interface;

    public class Sys_MenuLogic : LogicBase
    {
        /// <summary>
        /// 获取当前登录人账户信息
        /// </summary>
        protected AccountLogic accountLogic { get; }
        public Account userAccount { get; }

        public Sys_MenuLogic(HzySqlDbContext dbContext, AccountLogic accountLogic)
            : base(dbContext)
        {
            this.accountLogic = accountLogic;
            this.userAccount = this.accountLogic.UserAccount;
        }


        #region CURD 基础

        /// <summary>
        /// 获取数据源
        /// </summary>
        /// <param name="Page"></param>
        /// <param name="Rows"></param>
        /// <param name="Search"></param>
        /// <returns></returns>
        public async Task<TableViewModel> FindListAsync(int Page, int Rows, Sys_Menu Search)
        {
            var query = db.Query<Sys_Menu>()
                .Join<Sys_Menu>(w => w.t1.Menu_ParentID == w.t2.Menu_ID)
                .Where(w => w.t1.Menu_ParentID == null || w.t1.Menu_ParentID == Guid.Empty, Search.Menu_ID == Guid.Empty)
                .Where(w => w.t1.Menu_ParentID == Search.Menu_ID, Search.Menu_ID != Guid.Empty)
                .Where(w => w.t1.Menu_Name.Contains(Search.Menu_Name), !string.IsNullOrWhiteSpace(Search.Menu_Name))
                .Select(w => new
                {
                    w.t1.Menu_Name,
                    w.t1.Menu_Url,
                    父级菜单 = w.t2.Menu_Name,
                    w.t1.Menu_Num,
                    w.t1.Menu_Icon,
                    HzySql = w.Case().When(() => w.t1.Menu_IsShow == 2, "隐藏").Else("显示").End(nameof(w.t1.Menu_IsShow)),
                    w.t1.Menu_RoutePath,
                    w.t1.Menu_CreateTime,
                    _ukid = w.t1.Menu_ID
                })
                .OrderBy(w => w.t1.Menu_Num)
                .TakePage(Page, Rows, out int TotalCount)
                ;

            return await this.db.AsTableViewModelAsync(query, Page, Rows, TotalCount);
        }

        /// <summary>
        /// 新增\修改
        /// </summary>
        /// <param name="Dto"></param>
        /// <returns></returns>
        public async Task<Guid> SaveAsync(Sys_MenuDto Dto)
        {
            var model = Dto.Model;
            var functionIds = Dto.FunctionIds;

            try
            {
                db.AdoProvider.BeginTransaction();

                if (model.Menu_ID == Guid.Empty)
                {
                    model.Menu_ID = await db.Insert(model).SaveAsync<Guid>();
                }
                else
                {
                    await db.UpdateById(model).SaveAsync();
                }

                //
                await db.Delete<Sys_MenuFunction>(w => w.t1.MenuFunction_MenuID == model.Menu_ID).SaveAsync();
                if (functionIds.Count > 0)
                {
                    var _Sys_MenuFunctionList = await db.Query<Sys_MenuFunction>(w => w.t1.MenuFunction_MenuID == model.Menu_ID).ToListAsync();
                    foreach (var item in functionIds)
                    {
                        var _Sys_MenuFunction = _Sys_MenuFunctionList.FirstOrDefault(w => w.MenuFunction_FunctionID == item);
                        db.Insert(new Sys_MenuFunction
                        {
                            MenuFunction_ID = _Sys_MenuFunction == null ? Guid.NewGuid() : _Sys_MenuFunction.MenuFunction_ID,
                            MenuFunction_FunctionID = item,
                            MenuFunction_MenuID = model.Menu_ID
                        });
                    }
                }

                db.AdoProvider.Commit();
            }
            catch (Exception)
            {
                db.AdoProvider.Rollback();
                throw;
            }

            return model.Menu_ID;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="Keys"></param>
        /// <returns></returns>
        public async Task DeleteAsync(List<Guid> Ids)
        {
            this.iSqlContexts = new List<ISqlContext>();

            foreach (var item in Ids)
            {
                //删除菜单的功能
                db.Delete<Sys_RoleMenuFunction>(w => w.t1.RoleMenuFunction_MenuID == item).ToSqlContext(this.iSqlContexts);
                db.Delete<Sys_MenuFunction>(w => w.t1.MenuFunction_MenuID == item).ToSqlContext(this.iSqlContexts);
                db.DeleteById<Sys_Menu>(item).ToSqlContext(this.iSqlContexts);
            }

            //此函数用于批量 sql 操作
            await db.ExecuteBatchAsync(this.iSqlContexts);
        }

        /// <summary>
        /// 加载表单 数据
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<object> LoadFormAsync(Guid Id)
        {
            var Model = await db.FindByIdAsync<Sys_Menu>(Id);

            var AllFunctionList = await db.Query<Sys_Function>()
              .OrderBy(w => w.t1.Function_Num)
              .Select(w => new { w.t1.Function_ID, w.t1.Function_Name, w.t1.Function_ByName })
              .ToDictionaryListAsync();

            var FunctionIds = await db.Query<Sys_MenuFunction>(w => w.t1.MenuFunction_MenuID == Id).Select(w => w.t1.MenuFunction_FunctionID).ToListAsync<Guid>();

            return new { Id, Model, AllFunctionList, FunctionIds };
        }


        #endregion


        #region  创建系统左侧菜单

        /// <summary>
        /// 根据角色ID 获取菜单
        /// </summary>
        /// <returns></returns>
        public async Task<List<Sys_Menu>> GetMenuByRoleIDAsync()
        {
            var _Sys_MenuAllList = await db.Query<Sys_Menu>(w => w.t1.Menu_IsShow == 1).OrderBy(w => w.t1.Menu_Num).ToListAsync();
            if (this.userAccount.IsSuperManage) return _Sys_MenuAllList;

            var _Sys_MenuList = await db.Query<Sys_RoleMenuFunction>()
                .Join<Sys_Function>(w => w.t1.RoleMenuFunction_FunctionID == w.t2.Function_ID)
                .Join<Sys_Menu>(w => w.t1.RoleMenuFunction_MenuID == w.t3.Menu_ID)
                .Where(w => w.In(w.t1.RoleMenuFunction_RoleID, this.userAccount.RoleIDList.ToArray()))
                .Where(w => w.t2.Function_ByName == "Have")
                .Select(w => w.t3)
                .ToSqlContext(out ISqlContext sqlCode)
                .ToListAsync<Sys_Menu>();

            var _New_Sys_MenuList = new List<Sys_Menu>();

            for (int i = 0; i < _Sys_MenuList.Count; i++)
            {
                var item = _Sys_MenuList[i];
                this.CheckUpperLevel(_Sys_MenuAllList, _Sys_MenuList, _New_Sys_MenuList, item);
                if (!_New_Sys_MenuList.Any(w => w.Menu_ID == item.Menu_ID)) _New_Sys_MenuList.Add(item);
            }

            return _New_Sys_MenuList.OrderBy(w => w.Menu_Num).ToList();
        }

        private void CheckUpperLevel(List<Sys_Menu> sys_MenuAllList, List<Sys_Menu> old_Sys_MenuList, List<Sys_Menu> new_Sys_MenuList, Sys_Menu menu)
        {
            if (!old_Sys_MenuList.Any(w => w.Menu_ID == menu.Menu_ParentID.ToGuid()) && !new_Sys_MenuList.Any(w => w.Menu_ID == menu.Menu_ParentID))
            {
                var _Menu = sys_MenuAllList.Find(w => w.Menu_ID == menu.Menu_ParentID);
                if (_Menu != null)
                {
                    new_Sys_MenuList.Add(_Menu);
                    this.CheckUpperLevel(sys_MenuAllList, old_Sys_MenuList, new_Sys_MenuList, _Menu);
                }
            }
        }

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="_Sys_MenuList"></param>
        public List<object> CreateMenus(Guid Id, List<Sys_Menu> _Sys_MenuList)
        {
            var _Menus = new List<object>();
            List<Sys_Menu> _MenuItem = null;
            if (Id == Guid.Empty)
                _MenuItem = _Sys_MenuList.Where(w => w.Menu_ParentID == null || w.Menu_ParentID == Guid.Empty).ToList();
            else
                _MenuItem = _Sys_MenuList.Where(w => w.Menu_ParentID == Id).ToList();

            foreach (var item in _MenuItem)
            {
                _Menus.Add(new
                {
                    id = item.Menu_ID,
                    name = item.Menu_Name,
                    path = item.Menu_Url,
                    icon = item.Menu_Icon,
                    children = this.CreateMenus(item.Menu_ID.ToGuid(), _Sys_MenuList)
                });
            }
            return _Menus;
        }

        /// <summary>
        /// 获取拥有的菜单对象的权限
        /// </summary>
        /// <param name="_Sys_MenuList"></param>
        /// <returns></returns>
        public async Task<List<Dictionary<string, object>>> GetPowerState(List<Sys_Menu> _Sys_MenuList)
        {
            var _Sys_FunctionList = await db
                .Query<Sys_Function>()
                .OrderBy(w => w.t1.Function_Num)
                .ToListAsync();

            var _Sys_MenuFunctionList = await db
               .Query<Sys_MenuFunction>()
               .ToListAsync();

            var _Sys_RoleMenuFunctionList = await db
                .Query<Sys_RoleMenuFunction>(w => w.In(w.t1.RoleMenuFunction_RoleID, this.userAccount.RoleIDList.ToArray()))
                .ToListAsync();

            List<Dictionary<string, object>> _PowerStateList = new List<Dictionary<string, object>>();

            foreach (var item in _Sys_MenuList)
            {
                var _PowerState = new Dictionary<string, object>();

                if (this.userAccount.IsSuperManage)
                {
                    foreach (var _Sys_Function in _Sys_FunctionList)
                    {
                        var ispower = _Sys_MenuFunctionList.Any(w => w.MenuFunction_MenuID == item.Menu_ID && w.MenuFunction_FunctionID == _Sys_Function.Function_ID);
                        if (_Sys_Function.Function_ByName == "Have" | item.Menu_ParentID == AppConfig.AdminConfig.SysMenuID) ispower = true;
                        _PowerState.Add(_Sys_Function.Function_ByName, ispower);
                    }
                }
                else
                {
                    foreach (var _Sys_Function in _Sys_FunctionList)
                    {
                        if (this.userAccount.RoleIDList?.Count > 0)
                        {
                            var ispower = _Sys_RoleMenuFunctionList.Any(w =>
                                this.userAccount.RoleIDList.Contains(w.RoleMenuFunction_RoleID.ToGuid()) &&
                                w.RoleMenuFunction_MenuID == item.Menu_ID &&
                                w.RoleMenuFunction_FunctionID == _Sys_Function.Function_ID);
                            _PowerState.Add(_Sys_Function.Function_ByName, ispower);
                        }
                        else
                        {
                            _PowerState.Add(_Sys_Function.Function_ByName, false);
                        }
                    }
                }
                _PowerState["MenuID"] = item.Menu_ID;
                _PowerStateList.Add(_PowerState);
            }

            return _PowerStateList;
        }

        /// <summary>
        /// 根据菜单获取权限
        /// </summary>
        /// <param name="_Sys_Menu"></param>
        /// <returns></returns>
        public async Task<Dictionary<string, object>> GetPowerStateByMenuId(Guid MenuId)
        {
            var _Sys_Menu = await db.FindByIdAsync<Sys_Menu>(MenuId);

            var _Sys_FunctionList = await db
                .Query<Sys_Function>()
                .OrderBy(w => w.t1.Function_Num)
                .ToListAsync();

            var _Sys_MenuFunctionList = await db
               .Query<Sys_MenuFunction>(w => w.t1.MenuFunction_MenuID == _Sys_Menu.Menu_ID)
               .ToListAsync();

            var _Sys_RoleMenuFunctionList = await db
                .Query<Sys_RoleMenuFunction>(w => w.In(w.t1.RoleMenuFunction_RoleID, this.userAccount.RoleIDList.ToArray()))
                .ToListAsync();

            var _PowerState = new Dictionary<string, object>();

            if (this.userAccount.IsSuperManage)
            {
                foreach (var item in _Sys_FunctionList)
                {
                    var ispower = _Sys_MenuFunctionList.Any(w => w.MenuFunction_MenuID == _Sys_Menu.Menu_ID && w.MenuFunction_FunctionID == item.Function_ID);
                    if (item.Function_ByName == "Have" | _Sys_Menu.Menu_ParentID == AppConfig.AdminConfig.SysMenuID) ispower = true;
                    _PowerState.Add(item.Function_ByName, ispower);
                }
            }
            else
            {
                foreach (var item in _Sys_FunctionList)
                {
                    if (this.userAccount.RoleIDList?.Count > 0)
                    {
                        var ispower = _Sys_RoleMenuFunctionList.Any(w =>
                            this.userAccount.RoleIDList.Contains(w.RoleMenuFunction_RoleID.ToGuid()) &&
                            w.RoleMenuFunction_MenuID == _Sys_Menu.Menu_ID &&
                            w.RoleMenuFunction_FunctionID == item.Function_ID);
                        _PowerState.Add(item.Function_ByName, ispower);
                    }
                    else
                    {
                        _PowerState.Add(item.Function_ByName, false);
                    }
                }
            }

            return _PowerState;
        }

        #endregion  左侧菜单

        #region 创建菜单 功能 树

        public async Task<(List<object>, List<Guid>, List<string>)> GetMenuFunctionTreeAsync()
        {
            var _Sys_MenuList = await db.Query<Sys_Menu>().OrderBy(w => w.t1.Menu_Num).ToListAsync();
            var _Sys_FunctionList = await db.Query<Sys_Function>().OrderBy(w => w.t1.Function_Num).ToListAsync();
            var _Sys_MenuFunctionList = await db.Query<Sys_MenuFunction>().OrderBy(w => w.t1.MenuFunction_CreateTime).ToListAsync();
            List<Guid> DefaultExpandedKeys = new List<Guid>();
            List<string> DefaultCheckedKeys = new List<string>();
            var tree = this.CreateMenuFunctionTree(Guid.Empty, _Sys_MenuList, _Sys_FunctionList, _Sys_MenuFunctionList, DefaultExpandedKeys, DefaultCheckedKeys);
            return (tree, DefaultExpandedKeys, DefaultCheckedKeys);
        }

        /// <summary>
        /// 获取菜单与功能树
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="_Sys_MenuList"></param>
        /// <param name="_Sys_FunctionList"></param>
        /// <param name="_Sys_MenuFunctionList"></param>
        /// <param name="_DefaultExpandedKeys"></param>
        /// <param name="_DefaultCheckedKeys"></param>
        /// <returns></returns>
        private List<object> CreateMenuFunctionTree(Guid Id, List<Sys_Menu> _Sys_MenuList, List<Sys_Function> _Sys_FunctionList, List<Sys_MenuFunction> _Sys_MenuFunctionList, List<Guid> _DefaultExpandedKeys, List<string> _DefaultCheckedKeys)
        {
            var _Menus = new List<object>();
            List<Sys_Menu> _MenuItem = null;
            if (Id == Guid.Empty)
                _MenuItem = _Sys_MenuList.Where(w => w.Menu_ParentID == null || w.Menu_ParentID == Guid.Empty).ToList();
            else
                _MenuItem = _Sys_MenuList.Where(w => w.Menu_ParentID == Id).ToList();

            foreach (var item in _MenuItem)
            {
                var _children = new List<object>();
                if (_Sys_MenuList.Any(w => w.Menu_ParentID == item.Menu_ID))
                {
                    _DefaultExpandedKeys.Add(item.Menu_ID);

                    _children = this.CreateMenuFunctionTree(item.Menu_ID, _Sys_MenuList, _Sys_FunctionList, _Sys_MenuFunctionList, _DefaultExpandedKeys, _DefaultCheckedKeys);
                }
                else
                {
                    //if (string.IsNullOrWhiteSpace(item.Menu_Url)) continue;
                    //遍历功能
                    foreach (var _Function in _Sys_FunctionList)
                    {
                        //判断是否 该菜单下 是否勾选了 该功能
                        var _Sys_MenuFunction_Any = _Sys_MenuFunctionList.Any(w =>
                         w.MenuFunction_FunctionID == _Function.Function_ID &&
                         w.MenuFunction_MenuID == item.Menu_ID);

                        var id = $"{item.Menu_ID}${_Function.Function_ID}";
                        if (_Sys_MenuFunction_Any) _DefaultCheckedKeys.Add(id);

                        _children.Add(new
                        {
                            key = id,
                            title = $"{_Function.Function_Name}/{_Function.Function_ByName}({ _Function.Function_Num })",
                            disabled = true,
                            children = new ArrayList()
                        });
                    }

                }

                _Menus.Add(new
                {
                    key = item.Menu_ID,
                    title = $"{item.Menu_Name}/{item.Menu_Num}",
                    disableCheckbox = true,
                    children = _children
                });
            }

            return _Menus;
        }

        #endregion







    }
}
